home *** CD-ROM | disk | FTP | other *** search
- program group code
- code segment para public 'code'
- assume cs:program,ds:program
- ;
- org 80h
- parm_len db ?
- parm label byte
- org 100h
- ;
- begin: jmp main
- help_msg db 'usage: exe2com file1 [file2]'
- crlf db 13,10,'$'
- input_err db 'exe2com: unable to find input file $'
- output_err db 'exe2com: unable to open output file $'
- err_1 db 'invalid EXE file signature',13,10,'$'
- err_2 db 'EXE has relocatable items',13,10,'$'
- err_3 db 'EXE has stack segment',13,10,'$'
- err_4 db 'EXE has nonzero CS',13,10,'$'
- err_5 db 'IP not 0 or 100H',13,10,'$'
- err_6 db 'program exceeds 64K',13,10,'$'
- err_7 db 'error reading EXE file',13,10,'$'
- err_8 db 'error writing COM file',13,10,'$'
- cvt_msg_1 db 'converting $'
- cvt_msg_2 db 'to $'
- warn_msg db 'WARNING: COM file must have initial IP of 100H',13,10,'$'
- com_ext db '.COM'
- exe_ext db '.EXE'
- sys_ext db '.SYS'
- ;
- ; NOTE: Storage for file names allows for maximum of 128 byte drive/path/name
- ; plus 00H to end asciiz string and '$' to end DOS function 09H
- ;
- file_1 db 130 dup (0)
- file_2 db 130 dup (0)
- handle_1 dw 0
- handle_2 dw 0
- file_hdr dw 14 dup (0)
- file_buf db 512 dup (0)
- hdr_size dw 0
- code_size dw 0
- init proc near
- xor cx,cx
- mov cl,parm_len ;get length of command trailer from PSP
- inc cx
- lea si,parm
- lea di,file_1
- call get_name ;get input file name
- lea di,file_2
- call get_name ;get output file name
- xor ax,ax
- cmp al,file_1 ;if no input file
- jz bad_parm ;exit with error message
- cmp al,file_2 ;if no output file
- jz no_file_2 ;use same name as input
- jmp short check_ext
- no_file_2: lea si,file_1
- lea di,file_2
- mov cx,130
- move_filnm: lodsb ;get byte from input file name
- cmp al,'.'
- jz end_move ;don't move file extension
- cmp al,0
- end_move: stosb ;store byte in output file name
- loopnz move_filnm ;if not '.' or 00h get next
- dec di
- mov ax,2400h ;end with 00H and $
- stosw
- check_ext_1: lea si,file_1 ;if no extension
- lea dx,exe_ext ;on input file
- mov cx,130 ;default to EXE
- call check_ext
- check_ext_2: lea si,file_2 ;if no extension
- lea dx,com_ext ;on output file
- mov cx,130 ;default to EXE
- call check_ext
- end_init: ret
- bad_parm: lea dx,help_msg ;no files
- error_end: mov ah,9 ;display error message
- int 21h
- mov ax,4c01h ;terminate with return code 1
- int 21h
- init endp
- get_name proc near
- push di ;save destination address
- mov di,si
- mov al,' '
- repz scasb ;scan for first non-blank
- dec di
- mov si,di
- inc cx
- pop di ;restore destination
- get_byte: lodsb
- cmp al,' ' ;stop moving if blank
- jz short end_name
- cmp al,13 ;<cr> is end of command trailer
- jz short end_name
- cmp al,'a' ;convert to upper case
- jb store_byte
- cmp al,'z'
- ja store_byte
- sub al,32
- store_byte: stosb
- loop get_byte
- end_name: dec si
- mov ax,2400h ;end with 00H and $
- stosw
- ret
- get_name endp
- check_ext proc near
- lodsb
- cmp al,'.' ;if '.' found then file has ext
- jz check_end
- cmp al,0 ;end of file name
- loopnz check_ext
- dec si
- mov di,si
- mov si,dx ;DX contains address of default
- mov cx,4
- rep movsb ;move default extension
- mov ax,2400h ;end with 00H and '$'
- stosw
- check_end: ret
- check_ext endp
- read_hdr proc near
- lea dx,file_1
- mov ax,3d00h ;open the input file
- int 21h
- jb bad_file_1 ;error on open
- mov handle_1,ax ;save handle
- lea dx,file_hdr
- mov bx,handle_1
- mov cx,28 ;read 28 bytes
- mov ah,3fh ;of fixed header information
- int 21h
- jnb check_hdr
- jmp bad_read ;error on read
- check_hdr: mov ax,'ZM'
- cmp ax,file_hdr ;all EXE files begin with 'MZ'
- jnz not_exe
- mov ax,0
- cmp ax,file_hdr+6 ;number of relocatable items
- jnz has_relo ;must be 0
- mov ax,file_hdr+14
- or ax,file_hdr+16 ;SS and SP must be 0
- jnz has_ss
- cmp ax,file_hdr+22 ;CS offset must be 0
- jnz has_cs
- mov ax,file_hdr+20 ;initial IP
- cmp ax,100h ;must be 100H for COM file
- jz hdr_ok
- cmp ax,0 ;IP must be 0 or 100H
- jnz bad_ip
- call sys_file ;if IP=0 output will be .SYS file
- hdr_ok: mov ax,file_hdr+8
- mov cx,4 ;size of EXE file header
- shl ax,cl
- mov hdr_size,ax
- mov ax,file_hdr+4 ;number of 512 byte pages
- dec ax ;in EXE file
- mov bx,512
- mul bx ;multiply by 512
- add ax,file_hdr+2 ;add # of bytes in last page
- adc dx,0
- sub ax,hdr_size ;subtract header size
- sbb dx,0 ;to get size of program
- jnz too_big ;cannot be > 64K
- mov code_size,ax
- ret
- bad_file_1: lea dx,input_err ;couldn't open input file
- jmp error_end
- bad_file_2: lea dx,output_err ;couldn't open output file
- jmp error_end
- not_exe: lea dx,err_1 ;not a valid EXE file
- jmp error_end
- has_relo: lea dx,err_2 ;EXE has relocatable items
- jmp error_end
- has_ss: lea dx,err_3 ;EXE contains a stack segment
- jmp error_end
- has_cs: lea dx,err_4 ;EXE contains a CS offset
- jmp error_end
- bad_ip: lea dx,err_5 ;IP not 0 or 100H
- jmp error_end
- too_big: lea dx,err_6 ;file > 64K
- jmp error_end
- bad_read: lea dx,err_7 ;error reading input file
- jmp error_end
- bad_write: lea dx,err_8 ;error reading output file
- del_file: push dx ;conversion failed
- mov bx,handle_1 ;close input file
- mov ah,3eh
- int 21h
- mov bx,handle_2 ;close output file
- int 21h
- lea dx,file_2
- mov ah,41h ;delete output file
- int 21h
- pop dx
- jmp error_end
- read_hdr endp
- convert proc near
- lea dx,file_2 ;create output file
- xor cx,cx
- mov ah,3ch
- int 21h
- jb bad_file_2 ;couldn't create file
- mov handle_2,ax ;save file handle
- lea dx,cvt_msg_1 ;issue message
- mov ah,9 ;describing input
- int 21h ;and output files
- lea dx,file_1
- int 21h
- lea dx,cvt_msg_2
- int 21h
- lea dx,file_2
- int 21h
- lea dx,crlf
- int 21h
- mov dx,hdr_size ;add size of EXE file header
- mov cx,0 ;and
- add dx,file_hdr+20 ;initial IP
- adc cx,0 ;to get offset of actual code
- mov bx,handle_1
- mov ax,4200h ;set file pointer to beginning
- int 21h ;of actual code
- mov ax,code_size ;subtract IP from code size
- sub ax,file_hdr+20 ;to give # of bytes to write
- check_size: mov code_size,ax ;store # of bytes to write
- mov cx,512
- cmp cx,ax ;if bytes remaining > 512
- jna read_exe ;read 512 bytes
- mov cx,code_size ;otherwise read remaining
- read_exe: mov bx,handle_1
- lea dx,file_buf
- mov ah,3fh ;read EXE file
- int 21h
- jnb write_com
- jmp bad_read ;error reading
- write_com: mov bx,handle_2
- lea dx,file_buf
- mov ah,40h ;write to output file
- int 21h
- jnb next_read
- jmp bad_write ;error writing
- next_read: mov ax,code_size ;recall # of bytes to write
- sub ax,cx ;subtract # of bytes written
- jnz check_size ;to give # of bytes remaining
- close_files: mov bx,handle_1
- mov ah,3eh ;close input file
- int 21h
- mov bx,handle_2 ;close output file
- int 21h
- ret
- convert endp
- sys_file proc near ;change output file ext
- lea di,file_2 ;to .SYS
- mov al,'.'
- repnz scasb ;scan for '.'
- dec di
- lea si,com_ext
- mov cx,4
- repz cmpsb ;is ext .COM?
- jnz end_sys
- lea dx,warn_msg ;if so issue message
- mov ah,9
- int 21h
- sub di,4 ;and change it to .SYS
- lea si,sys_ext
- mov cx,4
- rep movsb
- end_sys: ret
- sys_file endp
- main: call init ;get input & output file names
- call read_hdr ;get fixed EXE file header
- call convert ;convert file
- mov ax,4c00h ;terminate with no return code
- int 21h
- code ends
- end begin